#pragma once

#include "Thread.hpp"
#include "GuardLock.hpp"
#include <iostream>
#include <vector>
#include <queue>
#include <string>

template <class T>
class ThreadPool;

template <class T>
struct ThreadData
{
    ThreadPool<T> *_pthreadpool;
    std::string _name;

    ThreadData(ThreadPool<T> *pthreadpool, std::string name)
        : _pthreadpool(pthreadpool), _name(name)
    {
    }
};

template <class T>
class ThreadPool
{
private:
    static const int gnum = 3;

private:
    static void *start_routine(void *args)
    {
        ThreadData<T> *threaddata = static_cast<ThreadData<T> *>(args);
        ThreadPool<T> *threadpool = threaddata->_pthreadpool;
        std::string threadname = threaddata->_name;

        while (true)
        {
            T t;
            threadpool->pop(&t);
            std::cout << threadname << " 处理任务 " << t.toString() << ", 处理完成，结果是：" << t() << std::endl;
        }
        delete threaddata;
        return nullptr;
    }

    ThreadPool(size_t num = gnum)
        : _num(num)
    {
        for (int i = 0; i < _num; i++)
        {
            //把线程池指针和线程名字同时传过去
            std::string name = "thread" + std::to_string(i + 1);
            ThreadData<T> *td = new ThreadData<T>(this, name);
            _threadpool.push_back(new Thread((void *)td));
        }
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }

public:

    ThreadPool(const ThreadPool&) = delete;
    ThreadPool& operator=(const ThreadPool&) = delete;

    // //传统写法
    // static ThreadPool* getInstance()
    // {
    //     //避免每次竞争锁，效率降低
    //     if(nullptr == tp)
    //     {
    //         GuardLock guardlock(&singmutex);
    //         if(tp == nullptr)
    //         {
    //             tp = new ThreadPool();
    //         }
    //     }

    //     return tp;
    // }

    //现代写法
    //不仅线程安全，还能自动析构
    static ThreadPool& getInstance()
    {
        static ThreadPool instance;
        return instance;
    }

    ~ThreadPool()
    {
        for (auto &e : _threadpool)
        {
            delete e;
        }
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

    void run()
    {
        for (int i = 0; i < _num; i++)
        {
            _threadpool[i]->start(start_routine);
        }
    }

    void push(const T &in)
    {
        //用RAII思想智能管理锁
        {
            GuardLock guardlock(&_mutex);
            _task.push(in);
            pthread_cond_signal(&_cond);
        }
    }

    void pop(T *out)
    {
        {
            GuardLock guardlock(&_mutex);
            while (_task.empty())
            {
                pthread_cond_wait(&_cond, &_mutex);
            }
            *out = _task.front();
            _task.pop();
        }
    }

private:
    std::vector<Thread *> _threadpool;
    size_t _num;
    std::queue<T> _task;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;

    // static ThreadPool* tp;
    // static pthread_mutex_t singmutex;
};

// template <class T>
// ThreadPool<T>* ThreadPool<T>::tp = nullptr;

// template <class T>
// pthread_mutex_t ThreadPool<T>::singmutex = PTHREAD_MUTEX_INITIALIZER;
